#ifndef DIRECTDRAW_H264_PLAY_H
#define DIRECTDRAW_H264_PLAY_H
#pragma  once

#include "GlobalDefs.h"
#include <stdio.h>
#include <boost/shared_ptr.hpp>
#include <map>
#ifdef SUPPORT_H264
#include "H264DecSDK.h"
#endif

#include "RawYUVFrameQueue.h"

#define MAX_READ_FILE_SIZE        (4096 * 4)
#define MAX_SOURCE_NAME_LENGTH    512
#define MAX_FRAME_SIZE            (1024*1024)
#define MAX_FPS                   120

typedef	struct {
	unsigned long channelNo;
	unsigned long videoLen;
	unsigned long timeTick;
	unsigned short audioLen;
	unsigned char bIFrame;
	unsigned char bVol;
} BtlFrameHeader;




class CDirectDisplay;
class DDrawH264Play
{
	typedef std::map<HMONITOR, boost::shared_ptr<CDirectDisplay>> CDirectDisplayMap;
public:
	DDrawH264Play(UINT fps, UINT width, UINT height, bool isRawYuv, bool isInterlaced);
	~DDrawH264Play(void);

	int StartPlay();
	int StopPlay();
	int PausePlay();

	void SetSourceName(const char *filename);
	void SetDataProvider(PLAYBACKSESSION session, DataProviderCallBack dataProvider, LPVOID param);
	const char *GetSourceName() { return m_srcName;}
	void SetOutputWindow(HWND hwnd);
	void UpdateVideoWindowRect();
	int SetDrawCallback(PLAYBACKSESSION session, DRAWCALLBACK drawCallback, long param);
	int SetDecodeCallback(PLAYBACKSESSION session, DECODECALLBACK decodeCallback, long param, bool needDisplay);
	int ChangePlaybackFps(UINT fps);
    //yb added for chengdu uestc,20111109
   // int SetFrameCallback(PLAYBACKSESSION session, FrameCALLBACK callback, long param);

	int GetBitrate();
	int GetActualFps();
	int GetActualVideoSize(int &width, int &height);

	int GetSnapshotSize();
	int Snapshot(char *buf, int bufLen);

	void UpdateActiveDirectDisplay();

	BOOL StartGetFrameThread();

private:
	CritSec              m_stateLock;                          //for synchronization between playback thread and the others
	bool                 m_isRawYuv;                           //display input yuv420 frame only(no h264 decoding)
	bool                 m_isInterlaced;                       //the input video stream is interlaced(need deinterlacing before display).
	HWND                 m_videoWnd;                           //where the video frames to be displayed.
	bool                 m_videoWndUpdateFlag;
	bool                 m_videoRectUpdateFlag;
	int                  m_demandWidth, m_demandHeight;        //user-set display image size.
	UINT                 m_demandFps;                          //user-set display fps.

	HANDLE               m_playThread;
	volatile int         m_playThreadCtrlFlag;
	bool				 m_pauseFlag;

	HANDLE               m_decodeThread;

	bool                 m_hasDecodeOneFrame;                  //if we have decoded a frame from h2y6
	UINT                 m_decodeWidth, m_decodeHeight;			
	bool                 m_beginNewFrame;
	BtlFrameHeader       m_header;
	UINT                 m_bytesForHeader;

	BYTE *               m_h264DataBuf;  //only for Decode,if origin Stream is not raw yuv data
	UINT                 m_h264DataLen;
	BYTE *               m_frameBuf1;
	BYTE *               m_frameBuf2;
	BYTE *               m_currFrameBuf; //for display
	UINT                 m_videoBufSize;

	BYTE*                m_CurDecodeFrame;
	RawYUVFrameQueue     m_frameQueue;



	//video stream data source
	bool                 m_isFileStream;
	char                 m_srcName[MAX_SOURCE_NAME_LENGTH];    
	FILE *               m_srcFile;
	DataProviderCallBack m_dataProvider;
	LPVOID               m_dataProviderParam;

	//callback functions
	CritSec              m_callbackLock;                       //for synchronization for access to callback functions
	PLAYBACKSESSION      m_playbackSession;
	DRAWCALLBACK         m_drawCallback;
	DECODECALLBACK       m_decodeCallback;
	bool                 m_needDisplay;
	long                 m_drawCallbackParam;
	long                 m_decodeCallbackParam;
	//long                 m_frameCallbackParam;//yb added for chengdu uestc,20111109

	//FrameCALLBACK        m_frameCallback;//yb added for chengdu uestc,20111109
	//runtime performance data
	DWORD                m_lastFpsCountTime;
	DWORD                m_lastActualFps;
	DWORD                m_totalFrame;
	DWORD                m_lastBitrateCountTime;
	DWORD                m_lastBitrate;
	UINT                 m_totalBit;
	DWORD                m_startTime;
	int                  m_frameCount;
	CDirectDisplayMap	 m_directDisplayMap;
	CDirectDisplay *	 m_pActiveDirectDisplay;
	DWORD				 m_dwLastCheckMonitorTick;

	int dispHeight;
	int dispWidth;

#ifdef SUPPORT_H264
	H264DECSESSION       m_decoderSession;

	bool DecodeH264Frame(void);
#endif

	bool GetH264Data(void);
	int DeinterlaceFrames(BYTE *destBuf, int destWidth, int destHeight);
	void AdjustVideoSize(int newWidth, int newHeight);

	void AllocateVideoBuffers(void);
	void ReleaseVideoBuffers(void);

	static unsigned int WINAPI PlayThreadProc(LPVOID param);
	static unsigned int WINAPI DecodeThreadProc(LPVOID param);
	//DWORD PlayThreadImpl(void);
	DWORD DecodeThreadImpl(void);
   
	void EnumDirectDisplay();
	static BOOL WINAPI DDEnumMonitorsProc(
		GUID FAR *lpGUID,    
		LPSTR     lpDriverDescription, 
		LPSTR     lpDriverName,        
		LPVOID    lpContext,           
		HMONITOR  hm        
		);

    static QUEUE_ACTION GetFrameDataProc(unsigned char* pData,int nSize,__int64 timeStamp, void* pUserData);	
    void InitPlay();

	static void EndGetFrameProc(void* pUserData);
	void StopGetFramethread();
	void CloseVideo();
};

#endif
